home *** CD-ROM | disk | FTP | other *** search
Text File | 1996-03-18 | 41.3 KB | 1,455 lines | [TEXT/ALFA] |
- // ===========================================================================
- //
- // GSGameScene.c
- //
- // Copyright (C) 1996 Apple Computer, Inc. All rights reserved.
- //
- // ===========================================================================
-
-
- // ===========================================================================
- // Includes
- // ===========================================================================
-
- #include <stdlib.h>
- #include <stdio.h>
-
- #include "RAVE.h"
-
- #include "GSGameScene.h"
- #include "GSImage.h"
- #include "GSPicture.h"
- #include "GSColorTable.h"
- #include "GSDrawInfo.h"
- #include "GSUtilities.h"
- #include "GSError.h"
-
-
- // ===========================================================================
- // Constants
- // ===========================================================================
-
- #define kVendorID_Apple 0
- #define kEngineID_AppleHardware (-1)
-
- #define kTextureTriCount 2
- #define kTextureTriGroupCount 10
-
- #define kClipping_front 0.0
- #define kClipping_back 10.0
-
- #define kBackgroundZ 0.9
- #define kBackgroundInvW (1.0 / 20.0)
- #define kWallsZ_front 0.1
- #define kWallsZ_back 0.8
- #define kWallsZeye_front 1.0
- #define kWallsZeye_back 6.0
- #define kWallsInvW_front (1.0 / kWallsZeye_front)
- #define kWallsInvW_back (1.0 / kWallsZeye_back)
-
- #define kBackground_U 4.0
- #define kBackground_V 4.0
- #define kWalls_U 5.0
- #define kWalls_V 1.0
- #define kBackWall_U 1.0
- #define kBackWall_V 1.0
- #define kFloor_U 1.0
- #define kFloor_V 5.0
-
- #define kColumn_left 0.25
- #define kColumn_right 0.5
- #define kColumn_top -0.5
- #define kColumn_bottom 0.5
- #define kColumnZ_front 2.0
- #define kColumnZ_back 2.25
-
- #define kColumnFrontU_min 0.0
- #define kColumnFrontU_max 0.25
- #define kColumnFrontV_min 0.0
- #define kColumnFrontV_max 1.0
- #define kColumnSideU_min 0.5
- #define kColumnSideU_max 0.75
- #define kColumnSideV_min 0.0
- #define kColumnSideV_max 1.0
-
- #define kBox1_left -0.5
- #define kBox1_right -0.1
- #define kBox1_top 0.1
- #define kBox1_bottom 0.5
- #define kBox1_front 1.1
- #define kBox1_back 1.9
- #define kBox1_triCount 100
-
- #define kTexture_background 0
- #define kTexture_leftWall 1
- #define kTexture_rightWall 2
- #define kTexture_backWall 3
- #define kTexture_floor 4
- #define kTexture_column 5
- #define kTexture_greenLava 6
- #define kTexture_redLava 7
- #define kTextureCount 8
-
- #define kGunZ 0.001
- #define kIntestines_Zeye 3.5
- #define kIntestines_Yeye 0.5
- #define kBitmap_gun 0
- #define kBitmap_intestines 1
- #define kBitmapCount 2
-
-
- // ===========================================================================
- // Types
- // ===========================================================================
-
- typedef struct TGSTextureTri {
- TQAVTexture v1;
- TQAVTexture v2;
- TQAVTexture v3;
- unsigned long flags;
- short texture;
- } TGSTextureTri;
-
- typedef struct TGSTextureTriGroup {
- TGSTextureTri tris[10];
- struct TGSTextureTriGroup* next;
- } TGSTextureTriGroup;
-
- typedef struct TGSTextureTriList {
- TGSTextureTriGroup* head;
- TGSTextureTriGroup* tail;
- unsigned char triIndex;
- } TGSTextureTriList;
-
-
- // ===========================================================================
- // Globals
- // ===========================================================================
-
- TGSDrawInfo* gDrawInfoP;
- float gWindowWidth;
- float gWindowHeight;
-
- unsigned long gTriFlags;
- TGSTextureTriList gTextureTriList;
-
- TQATexture* gTextures[kTextureCount];
- TGSImage* gTextureImages[kTextureCount];
- TQAColorTable* gTextureColorTables[kTextureCount];
-
- #if (kQAPlatform == kQAMacOS)
- char* gTextureFileNames[kTextureCount] = {
- "GS_Stars.16.pict",
- "GS_DarkBrownWall.16.pict",
- "GS_GreenBrownOvalWall.16.pict",
- "GS_ShipDoor.16.pict",
- "GS_GreyFloor.16.pict",
- "GS_YellowBlackStripes.16.pict",
- "GS_GreenLava.16.pict",
- "GS_RedLava.16.pict"
- };
- #endif
-
- TQABitmap* gBitmaps[kBitmapCount];
- TGSImage* gBitmapImages[kBitmapCount];
- TQAColorTable* gBitmapColorTables[kBitmapCount];
-
- #if (kQAPlatform == kQAMacOS)
- char* gBitmapFileNames[kBitmapCount] = {
- "GS_AssaultRifle.cl8.pict",
- "GS_Intestines.cl8.pict"
- };
- #endif
-
-
- // ===========================================================================
- // Prototypes
- // ===========================================================================
-
- TGSError
- GSLoadTextures(
- TGSDrawInfo* inDrawInfo);
-
- void
- GSUnloadTextures(
- TGSDrawInfo* inDrawInfo);
-
- TGSError
- GSLoadBitmaps(
- TGSDrawInfo* inDrawInfo);
-
- void
- GSUnloadBitmaps(
- TGSDrawInfo* inDrawInfo);
-
- void
- GSDrawBitmaps(
- TGSDrawInfo* inDrawInfo);
-
- void
- GSBoundedRandomVTexture(
- TQAVTexture* inVertex,
- float inLeft,
- float inRight,
- float inTop,
- float inBottom,
- float inFront,
- float inBack);
-
- void
- GSRandomRGBDefaultHighlight(
- TQAVTexture* inVertex);
-
- float
- GSGetScreenX(
- float inX,
- float inZ);
-
- float
- GSGetScreenY(
- float inY,
- float inZ);
-
- float
- GSGetScreenZ(
- float inZ);
-
- void
- GSStoreBackground(
- float inWidth,
- float inHeight,
- float inDepth);
- void GSStoreColumn();
-
- void
- GSStoreWalls(
- float inBackWidth,
- float inBackHeight,
- float inFrontZ,
- float inBackZ);
-
- void
- GSStoreRandomTris(void);
-
- Boolean
- GSTextureTriList_New(
- TGSTextureTriList* inTextureTriList);
-
- void
- GSTextureTriList_Delete(
- TGSTextureTriList* inTextureTriList);
-
- Boolean
- GSTextureTriList_IsValid(
- TGSTextureTriList* inTextureTriList);
-
- Boolean
- GSTextureTriList_NewTextureTriGroup(
- TGSTextureTriList* inTextureTriList);
-
- Boolean
- GSTextureTriList_StoreTri(
- TGSTextureTriList* inTextureTriList,
- TQAVTexture* inVert1,
- TQAVTexture* inVert2,
- TQAVTexture* inVert3,
- unsigned long inFlags,
- short inTexture);
-
- Boolean
- GSTextureTriList_StoreQuad(
- TGSTextureTriList* inTextureTriList,
- TQAVTexture* inVert1,
- TQAVTexture* inVert2,
- TQAVTexture* inVert3,
- TQAVTexture* inVert4,
- unsigned long inFlags,
- short inTexture);
-
- void
- GSTextureTriList_Draw(
- TGSTextureTriList* inTextureTriList,
- TGSDrawInfo* inDrawInfo);
-
-
- // ===========================================================================
- // GSTestGameScene
- // ===========================================================================
- TGSError
- GSDrawGameScene(
- TGSDrawInfo* inDrawInfo)
- {
- char drawBitmapsFlagString[4] = "";
- TGSError gsError = kGSError_None;
-
- if (GSTextureTriList_New(&gTextureTriList) == false) {
- // there's not enough memory to store the tris, so we can't
- // run the test
- return kGSError_NotEnoughMemory;
- }
-
- gDrawInfoP = inDrawInfo;
-
- // all the triangles are front-facing, so use "none"
- // for the flags parameter
- gTriFlags = kQATriFlags_None;
-
- // set up the window size globals
- gWindowWidth = inDrawInfo->mContextRect.right - inDrawInfo->mContextRect.left;
- gWindowHeight = inDrawInfo->mContextRect.bottom - inDrawInfo->mContextRect.top;
-
- gsError = GSLoadTextures(inDrawInfo);
-
- if (gsError != kGSError_None) {
- // there was a problem while loading the textures, so don't do
- // any drawing and skip right to the cleanup
- goto cleanup;
- }
-
- gsError = GSLoadBitmaps(inDrawInfo);
-
- if (gsError != kGSError_None) {
- // there was a problem while loading the bitmaps, so don't do
- // any drawing and skip right to the cleanup
- goto cleanup;
- }
-
- GSStoreBackground(gWindowWidth, gWindowHeight, kBackgroundZ);
-
- GSStoreWalls(
- gWindowWidth * (1.0 / 6.0), gWindowHeight * (1.0 / 6.0),
- kWallsZ_front, kWallsZ_back);
-
- GSStoreColumn();
-
- GSStoreRandomTris();
-
- if (!GSTextureTriList_IsValid(&gTextureTriList)) {
- // at some point we ran out of memory in which to store new
- // tris, so we can't run the test
- gsError = kGSError_NotEnoughMemory;
- goto cleanup;
- }
-
- // prepare to render into the draw context
- QARenderStart(inDrawInfo->mContext, nil, nil);
-
- // render all the triangles we've stored in the tri list
- GSTextureTriList_Draw(&gTextureTriList, inDrawInfo);
-
- GSDrawBitmaps(inDrawInfo);
-
- // let the engine know we've finished rendering
- QARenderEnd(inDrawInfo->mContext, nil);
-
- // wait for the engine to catch up and finish drawing everything
- QASync(inDrawInfo->mContext);
-
- cleanup:
- GSTextureTriList_Delete(&gTextureTriList);
- GSUnloadTextures(inDrawInfo);
- GSUnloadBitmaps(inDrawInfo);
-
- return gsError;
- }
-
-
- // ===========================================================================
- // GSLoadTextures
- // ===========================================================================
- TGSError
- GSLoadTextures(
- TGSDrawInfo* inDrawInfo)
- {
- TGSPicture* picture = nil;
- TQAError qaError = kQANoErr;
- TGSError gsError = kGSError_None;
- TGSError result = kGSError_None;
- short i;
-
- for (i = 0; i < kTextureCount; i++) {
- // read the picture data from the file in gTextureFileNames into a
- // TGSPicture. this object handles any necessary conversion from
- // the format of the picture data in the file to the RAVE texture
- // format. the disposal of this picture will be handled by the
- // TGSImage we create below.
- gsError = GSPicture_NewFromPath(&picture, inDrawInfo->mTextureFormat,
- gTextureFileNames[i]);
-
- if (gsError != kGSError_None) {
- // we couldn't find the picture file, so record an error and
- // then try the next one
- result = gsError;
-
- continue;
- }
-
- // create a TGSImage from the TGSPicture we just created above.
- // this object fills in the TQAImage structure with the appropriate
- // values from the TGSPicture. it will also optionally make every
- // black pixel in the picture transparent and create mip maps for
- // the texture. it handles the disposal of the TGSPicture. we use
- // the TGSImage below to create an actual RAVE texture.
- gsError = GSImage_NewFromPicture(&gTextureImages[i], picture,
- inDrawInfo->mTextureFormat, inDrawInfo->mTextureMakeBlackTransparent,
- inDrawInfo->mTextureMakeMipMap);
-
- if (gsError != kGSError_None) {
- // for some reason we couldn't create a GSImage (probably
- // not enough memory), so break out of the loop. we break instead
- // of continuing since if there's not enough memory, there's no
- // point going on.
- result = gsError;
-
- break;
- }
-
- if (inDrawInfo->mTextureMakeMipMap && !GSImage_IsValidMipMap(gTextureImages[i])) {
- // the texture is supposed to be mipmapped, but GSImage couldn't
- // mip map it for some reason
- result = kGSError_RAVE;
-
- break;
- }
-
- // try to create a texture for the engine, using the image data
- // stored in the TGSImage in gTextureImages[i]
- qaError = QATextureNew(inDrawInfo->mEngine, inDrawInfo->mTextureFlags,
- GSImage_GetPixelType(gTextureImages[i]),
- GSImage_GetImages(gTextureImages[i]),
- &gTextures[i]);
-
- if (qaError != kQANoErr) {
- // for some reason the engine couldn't create a texture (probably
- // not enough memory), so break out of the loop. we break
- // instead of continuing since if there's not enough memory,
- // there's no point going on.
- result = kGSError_RAVE;
-
- break;
- }
-
- if (inDrawInfo->mTextureFormat == kQAPixel_CL4 ||
- inDrawInfo->mTextureFormat == kQAPixel_CL8) {
- TGSColorTable* colorTableP = GSImage_GetColorTable(gTextureImages[i]);
- GSAssert_(colorTableP);
-
- // create a new color table in the engine from the color table
- // data in the TGSImage. when a TGSPicture is created, it also
- // creates a TGSColorTable, if necessary, which in turn stores
- // the color table from the picture file in an array of pixels
- // in TQAImagePixelType format. we can get the TGSColorTable
- // out of the TGSImage by calling GSImage_GetColorTable.
- //
- // once the color table data has been used to create a
- // TQAColorTable, we can delete it. in this case, however, it
- // won't be deleted until the TGSPicture which stores it is
- // itself deleted.
- qaError = QAColorTableNew(inDrawInfo->mEngine,
- GSColorTable_GetType(colorTableP),
- GSColorTable_GetData(colorTableP),
- inDrawInfo->mTextureUseTransparentIndex,
- &gTextureColorTables[i]);
-
- if (qaError != kQANoErr) {
- // we couldn't create a color table in this engine (perhaps
- // it doesn't support CL textures), so break out of the loop,
- // since we can't continue if the engine can't create
- // color tables.
- result = kGSError_RAVE;
-
- break;
- }
-
- // bind this color table to the texture.
- qaError = QATextureBindColorTable(inDrawInfo->mEngine,
- gTextures[i], gTextureColorTables[i]);
-
- if (qaError != kQANoErr) {
- // we couldn't bind this color table to the texture in
- // this engine, so break out of the loop, since we won't
- // be able to draw this texture
- result = kGSError_RAVE;
-
- break;
- }
- }
-
- if (inDrawInfo->mTextureDetach) {
- // try to detach the texture from the engine
- qaError = QATextureDetach(inDrawInfo->mEngine, gTextures[i]);
-
- // if the texture was successfully detached, delete the image
- // which stores the texture's pixmap, since the engine now
- // has its own copy of that data. if the texture couldn't be
- // detached, don't do anything (i.e., hold on to the image).
- if (qaError == kQANoErr) {
- GSImage_Delete(gTextureImages[i]);
- gTextureImages[i] = nil;
- }
- }
- } // endfor
-
- return result;
- }
-
-
- // ===========================================================================
- // GSUnloadTextures
- // ===========================================================================
- void
- GSUnloadTextures(
- TGSDrawInfo* inDrawInfo)
- {
- short i;
-
- for (i = 0; i < kTextureCount; i++) {
- // dispose of the textures
- if (gTextures[i] != nil) {
- QATextureDelete(inDrawInfo->mEngine, gTextures[i]);
- gTextures[i] = nil;
- }
-
- // dispose of the color tables
- if (gTextureColorTables[i] != nil) {
- QAColorTableDelete(inDrawInfo->mEngine, gTextureColorTables[i]);
- gTextureColorTables[i] = nil;
- }
-
- // dispose of the image which is referenced by the texture
- if (gTextureImages[i] != nil) {
- GSImage_Delete(gTextureImages[i]);
- gTextureImages[i] = nil;
- }
- }
- }
-
-
- // ===========================================================================
- // GSLoadBitmaps
- // ===========================================================================
- TGSError
- GSLoadBitmaps(
- TGSDrawInfo* inDrawInfo)
- {
- TGSPicture* picture = nil;
- TQAError qaError = kQANoErr;
- TGSError gsError = kGSError_None;
- TGSError result = kGSError_None;
- short i;
-
- for (i = 0; i < kBitmapCount; i++) {
- // read the picture data from the file in gBitmapFileNames into a
- // TGSPicture. this object handles any necessary conversion from
- // the format of the picture data in the file to the RAVE bitmap
- // format. the disposal of this picture will be handled by the
- // TGSImage we create below.
- gsError = GSPicture_NewFromPath(&picture, inDrawInfo->mBitmapFormat,
- gBitmapFileNames[i]);
-
- if (gsError != kGSError_None) {
- // we couldn't find the picture file, so record an error and
- // then try the next one
- result = gsError;
-
- continue;
- }
-
- // create a TGSImage from the TGSPicture we just created above.
- // this object fills in the TQAImage structure with the appropriate
- // values from the TGSPicture. it will also optionally make every
- // black pixel in the picture transparent and create mip maps for
- // the bitmap. it handles the disposal of the TGSPicture. we use
- // the TGSImage below to create an actual RAVE bitmap.
- gsError = GSImage_NewFromPicture(&gBitmapImages[i], picture,
- inDrawInfo->mBitmapFormat,
- inDrawInfo->mBitmapMakeBlackTransparent, false);
-
- if (gsError != kGSError_None) {
- // for some reason we couldn't create a GSImage (probably
- // not enough memory), so break out of the loop. we break instead
- // of continuing since if there's not enough memory, there's no
- // point going on.
- result = gsError;
-
- break;
- }
-
- // try to create a bitmap for the engine, using the image data
- // stored in the TGSImage in gBitmapImages[i]
- qaError = QABitmapNew(inDrawInfo->mEngine, inDrawInfo->mBitmapFlags,
- GSImage_GetPixelType(gBitmapImages[i]),
- GSImage_GetImages(gBitmapImages[i]),
- &gBitmaps[i]);
-
- if (qaError != kQANoErr) {
- // for some reason the engine couldn't create a bitmap (probably
- // not enough memory), so break out of the loop. we break
- // instead of continuing since if there's not enough memory,
- // there's no point going on.
- result = kGSError_RAVE;
-
- break;
- }
-
- if (inDrawInfo->mBitmapFormat == kQAPixel_CL4 ||
- inDrawInfo->mBitmapFormat == kQAPixel_CL8) {
- TGSColorTable* colorTableP = GSImage_GetColorTable(gBitmapImages[i]);
- GSAssert_(colorTableP);
-
- // create a new color table in the engine from the color table
- // data in the TGSImage. when a TGSPicture is created, it also
- // creates a TGSColorTable, if necessary, which in turn stores
- // the color table from the picture file in an array of pixels
- // in TQAImagePixelType format. we can get the TGSColorTable
- // out of the TGSImage by calling GSImage_GetColorTable.
- //
- // once the color table data has been used to create a
- // TQAColorTable, we can delete it. in this case, however, it
- // won't be deleted until the TGSPicture which stores it is
- // itself deleted.
- qaError = QAColorTableNew(inDrawInfo->mEngine,
- GSColorTable_GetType(colorTableP),
- GSColorTable_GetData(colorTableP),
- inDrawInfo->mBitmapUseTransparentIndex,
- &gBitmapColorTables[i]);
-
- if (qaError != kQANoErr) {
- // we couldn't create a color table in this engine (perhaps
- // it doesn't support CL bitmaps), so break out of the loop,
- // since we can't continue if the engine can't create
- // color tables.
- result = kGSError_RAVE;
-
- break;
- }
-
- // bind this color table to the bitmap
- qaError = QABitmapBindColorTable(inDrawInfo->mEngine,
- gBitmaps[i], gBitmapColorTables[i]);
-
- if (qaError != kQANoErr) {
- // we couldn't bind this color table to the bitmap in
- // this engine, so break out of the loop, since we won't
- // be able to draw this bitmap
- result = kGSError_RAVE;
-
- break;
- }
- }
-
- if (inDrawInfo->mBitmapDetach) {
- // try to detach the bitmap from the engine
- qaError = QABitmapDetach(inDrawInfo->mEngine, gBitmaps[i]);
-
- // if the bitmap was successfully detached, delete the image
- // which stores the bitmap's pixmap, since the engine now
- // has its own copy of that data. if the bitmap couldn't be
- // detached, don't do anything (i.e., hold on to the image).
- if (qaError == kQANoErr) {
- GSImage_Delete(gBitmapImages[i]);
- gBitmapImages[i] = nil;
- }
- }
- } // endfor
-
- return result;
- }
-
-
- // ===========================================================================
- // GSUnloadBitmaps
- // ===========================================================================
- void
- GSUnloadBitmaps(
- TGSDrawInfo* inDrawInfo)
- {
- short i;
-
- for (i = 0; i < kBitmapCount; i++) {
- // dispose of the bitmaps
- if (gBitmaps[i] != nil) {
- QABitmapDelete(inDrawInfo->mEngine, gBitmaps[i]);
- gBitmaps[i] = nil;
- }
-
- // dispose of the color tables
- if (gBitmapColorTables[i] != nil) {
- QAColorTableDelete(inDrawInfo->mEngine, gBitmapColorTables[i]);
- gBitmapColorTables[i] = nil;
- }
-
- // dispose of the image which is referenced by the bitmap
- if (gBitmapImages[i] != nil) {
- GSImage_Delete(gBitmapImages[i]);
- gBitmapImages[i] = nil;
- }
- }
- }
-
-
- // ===========================================================================
- // GSDrawBitmaps
- // ===========================================================================
- void
- GSDrawBitmaps(
- TGSDrawInfo* inDrawInfo)
- {
- // eyeZ / eyeZrange == screenZ / screenZrange
- // solve for screenZ to get a Z value between 0 and 1 for intestines
- float eyeZrange = kWallsZeye_back - kWallsZeye_front;
- float screenZrange = kWallsZ_back - kWallsZ_front;
- float intestinesZ = (kIntestines_Zeye / eyeZrange) * screenZrange;
- TQAVGouraud v;
-
- // set the color and alpha to white
- v.r = v.g = v.b = v.a = 1.0;
-
- // center the gun bitmap horizontally and place it at the bottom of
- // the window
- v.x = (gWindowWidth - GSImage_GetWidth(gBitmapImages[kBitmap_gun])) / 2.0;
- v.y = gWindowHeight - GSImage_GetHeight(gBitmapImages[kBitmap_gun]);
- v.z = kGunZ;
- v.invW = 1.0 / kGunZ;
-
- // draw the assault rifle bitmap
- QADrawBitmap(inDrawInfo->mContext, &v, gBitmaps[kBitmap_gun]);
-
- // center the intestines bitmap horizontally and place it so its
- // bottom touches the floor at its Zeye coord, which affects its
- // vertical coord on the screen.
- v.x = (gWindowWidth - GSImage_GetWidth(gBitmapImages[kBitmap_intestines])) / 2.0;
- v.y = GSGetScreenY(kIntestines_Yeye, kIntestines_Zeye) - GSImage_GetHeight(gBitmapImages[kBitmap_intestines]);
- v.z = intestinesZ;
- v.invW = 1.0 / intestinesZ;
-
- // draw the bitmap in both contexts
- QADrawBitmap(inDrawInfo->mContext, &v, gBitmaps[kBitmap_intestines]);
- }
-
-
- // ===========================================================================
- // GSGetScreenX
- // ===========================================================================
- float
- GSGetScreenX(
- float inX,
- float inZ)
- {
- return (gWindowWidth * (0.5 + (inX / inZ)));
- }
-
-
- // ===========================================================================
- // GSGetScreenY
- // ===========================================================================
- float
- GSGetScreenY(
- float inY,
- float inZ)
- {
- // because screen Y values diminish towards the top of the screen,
- // eye Y (inY) values are assumed to be positive towards the bottom
- // of the screen and negative towards the top.
- return (gWindowHeight * (0.5 + (inY / inZ)));
- }
-
-
- // ===========================================================================
- // GSGetScreenZ
- // ===========================================================================
- float
- GSGetScreenZ(
- float inZ)
- {
- // inZ is assumed to be less than kClipping_back. this maps the
- // the eye-space Z to a value between 0 and 1
- return (inZ / kClipping_back);
- }
-
-
- // ===========================================================================
- // GSBoundedRandomVTexture
- // ===========================================================================
- void
- GSBoundedRandomVTexture(
- TQAVTexture* inVertex,
- float inLeft,
- float inRight,
- float inTop,
- float inBottom,
- float inFront,
- float inBack)
- {
- float rangeX = inRight - inLeft;
- float rangeY = inBottom - inTop;
- float rangeZ = inBack - inFront;
-
- // first random values in eye space
- inVertex->x = inLeft + rangeX * GSRandomFloat();
- inVertex->y = inTop + rangeY * GSRandomFloat();
- inVertex->z = inFront + rangeZ * GSRandomFloat();
-
- // invert the eye-space Z coord to get invW
- inVertex->invW = 1.0 / inVertex->z;
-
- // now convert these to screen space
- inVertex->x = GSGetScreenX(inVertex->x, inVertex->z);
- inVertex->y = GSGetScreenY(inVertex->y, inVertex->z);
- inVertex->z = GSGetScreenZ(inVertex->z);
-
- // make random U and V between 0 and 2
- inVertex->uOverW = 2.0 * GSRandomFloat() * inVertex->invW;
- inVertex->vOverW = 2.0 * GSRandomFloat() * inVertex->invW;
-
- // get random RGB values
- inVertex->a = 1.0;
- inVertex->r = GSRandomFloat();
- inVertex->g = GSRandomFloat();
- inVertex->b = GSRandomFloat();
-
- inVertex->kd_r = 1.0;
- inVertex->kd_g = 1.0;
- inVertex->kd_b = 1.0;
-
- inVertex->ks_r = 0.0;
- inVertex->ks_g = 0.0;
- inVertex->ks_b = 0.0;
- }
-
-
- // ===========================================================================
- // GSRandomRGBDefaultHighlight
- // ===========================================================================
- void
- GSRandomRGBDefaultHighlight(
- TQAVTexture* inVertex)
- {
- // make the vertex's RGB values random
- inVertex->r = GSRandomFloat();
- inVertex->g = GSRandomFloat();
- inVertex->b = GSRandomFloat();
-
- // make the alpha and highlight values "default"
- inVertex->a = 1.0;
-
- inVertex->kd_r = 1.0;
- inVertex->kd_g = 1.0;
- inVertex->kd_b = 1.0;
-
- inVertex->ks_r = 0.0;
- inVertex->ks_g = 0.0;
- inVertex->ks_b = 0.0;
- }
-
-
- // ===========================================================================
- // GSStoreBackground
- // ===========================================================================
- void
- GSStoreBackground(
- float inWidth,
- float inHeight,
- float inDepth)
- {
- TQAVTexture verts[4];
-
- // we subtract a little bit from the width and height values so that
- // they're fully inside the screen pixels
- inWidth -= 0.1;
- inHeight -= 0.1;
-
- // the background tris all have the same depth and invW
- verts[0].z = verts[1].z = verts[2].z = verts[3].z = inDepth;
- verts[0].invW = verts[1].invW = verts[2].invW = verts[3].invW = kBackgroundInvW;
-
- // all tri vertices will have random RGB values, default highlight
- GSRandomRGBDefaultHighlight(&verts[0]);
- GSRandomRGBDefaultHighlight(&verts[1]);
- GSRandomRGBDefaultHighlight(&verts[2]);
- GSRandomRGBDefaultHighlight(&verts[3]);
-
- verts[0].x = 0.0;
- verts[0].y = 0.0;
- verts[0].uOverW = 0.0;
- verts[0].vOverW = kBackground_V * verts[0].invW;
-
- verts[1].x = 0.0;
- verts[1].y = inHeight;
- verts[1].uOverW = 0.0;
- verts[1].vOverW = 0.0;
-
- verts[2].x = inWidth;
- verts[2].y = inHeight;
- verts[2].uOverW = kBackground_U * verts[2].invW;
- verts[2].vOverW = 0.0;
-
- verts[3].x = inWidth;
- verts[3].y = 0.0;
- verts[3].uOverW = kBackground_U * verts[3].invW;
- verts[3].vOverW = kBackground_V * verts[3].invW;
-
- // store the background rectangle
- GSTextureTriList_StoreQuad(
- &gTextureTriList,
- &verts[0],
- &verts[1],
- &verts[2],
- &verts[3],
- gTriFlags,
- kTexture_background);
- }
-
-
- // ===========================================================================
- // GSStoreColumn
- // ===========================================================================
- void
- GSStoreColumn()
- {
- TQAVTexture verts[4];
-
- // eyeZ / eyeZrange == screenZ / screenZrange
- // solve for screenZ to get a Z value between 0 and 1 for the front
- // and side of the column
- float eyeZrange = kWallsZeye_back - kWallsZeye_front;
- float screenZrange = kWallsZ_back - kWallsZ_front;
- float columnScreenZ_front = (kColumnZ_front / eyeZrange) * screenZrange;
- float columnScreenZ_back = (kColumnZ_back / eyeZrange) * screenZrange;
-
- // all tri vertices will have random RGB values, default highlight
- GSRandomRGBDefaultHighlight(&verts[0]);
- GSRandomRGBDefaultHighlight(&verts[1]);
- GSRandomRGBDefaultHighlight(&verts[2]);
- GSRandomRGBDefaultHighlight(&verts[3]);
-
- // front of column
- verts[0].x = GSGetScreenX(kColumn_left, kColumnZ_front);
- verts[0].y = GSGetScreenY(kColumn_top, kColumnZ_front);
- verts[0].z = columnScreenZ_front;
- verts[0].invW = 1.0 / kColumnZ_front;
- verts[0].uOverW = kColumnFrontU_min * verts[0].invW;
- verts[0].vOverW = kColumnFrontV_max * verts[0].invW;
-
- verts[1].x = GSGetScreenX(kColumn_left, kColumnZ_front);
- verts[1].y = GSGetScreenY(kColumn_bottom, kColumnZ_front);
- verts[1].z = columnScreenZ_front;
- verts[1].invW = 1.0 / kColumnZ_front;
- verts[1].uOverW = kColumnFrontU_min * verts[1].invW;
- verts[1].vOverW = kColumnFrontV_min * verts[1].invW;
-
- verts[2].x = GSGetScreenX(kColumn_right, kColumnZ_front);
- verts[2].y = GSGetScreenY(kColumn_bottom, kColumnZ_front);
- verts[2].z = columnScreenZ_front;
- verts[2].invW = 1.0 / kColumnZ_front;
- verts[2].uOverW = kColumnFrontU_max * verts[2].invW;
- verts[2].vOverW = kColumnFrontV_min * verts[2].invW;
-
- verts[3].x = GSGetScreenX(kColumn_right, kColumnZ_front);
- verts[3].y = GSGetScreenY(kColumn_top, kColumnZ_front);
- verts[3].z = columnScreenZ_front;
- verts[3].invW = 1.0 / kColumnZ_front;
- verts[3].uOverW = kColumnFrontU_max * verts[3].invW;
- verts[3].vOverW = kColumnFrontV_max * verts[3].invW;
-
- GSTextureTriList_StoreQuad(
- &gTextureTriList,
- &verts[0],
- &verts[1],
- &verts[2],
- &verts[3],
- gTriFlags,
- kTexture_column);
-
- // side of column
- verts[0].x = GSGetScreenX(kColumn_left, kColumnZ_back);
- verts[0].y = GSGetScreenY(kColumn_top, kColumnZ_back);
- verts[0].z = columnScreenZ_back;
- verts[0].invW = 1.0 / kColumnZ_back;
- verts[0].uOverW = kColumnSideU_min * verts[0].invW;
- verts[0].vOverW = kColumnSideV_max * verts[0].invW;
-
- verts[1].x = GSGetScreenX(kColumn_left, kColumnZ_back);
- verts[1].y = GSGetScreenY(kColumn_bottom, kColumnZ_back);
- verts[1].z = columnScreenZ_front;
- verts[1].invW = 1.0 / kColumnZ_back;
- verts[1].uOverW = kColumnSideU_min * verts[1].invW;
- verts[1].vOverW = kColumnSideV_min * verts[1].invW;
-
- verts[2].x = GSGetScreenX(kColumn_left, kColumnZ_front);
- verts[2].y = GSGetScreenY(kColumn_bottom, kColumnZ_front);
- verts[2].z = columnScreenZ_front;
- verts[2].invW = 1.0 / kColumnZ_front;
- verts[2].uOverW = kColumnSideU_max * verts[2].invW;
- verts[2].vOverW = kColumnSideV_min * verts[2].invW;
-
- verts[3].x = GSGetScreenX(kColumn_left, kColumnZ_front);
- verts[3].y = GSGetScreenY(kColumn_top, kColumnZ_front);
- verts[3].z = columnScreenZ_front;
- verts[3].invW = 1.0 / kColumnZ_front;
- verts[3].uOverW = kColumnSideU_max * verts[3].invW;
- verts[3].vOverW = kColumnSideV_max * verts[3].invW;
-
- GSTextureTriList_StoreQuad(
- &gTextureTriList,
- &verts[0],
- &verts[1],
- &verts[2],
- &verts[3],
- gTriFlags,
- kTexture_column);
- }
-
-
- // ===========================================================================
- // GSStoreWalls
- // ===========================================================================
- void
- GSStoreWalls(
- float inBackWidth,
- float inBackHeight,
- float inFrontZ,
- float inBackZ)
- {
- float windowWidth = gWindowWidth - 0.1;
- float windowHeight = gWindowHeight - 0.1;
- float wallWidth = (windowWidth - inBackWidth) / 2.0;
- float floorDepth = (windowHeight - inBackHeight) / 2.0;
- float maxUV = 5.0;
- TQAVTexture verts[4];
-
- // all tri vertices will have random RGB values, default highlight
- GSRandomRGBDefaultHighlight(&verts[0]);
- GSRandomRGBDefaultHighlight(&verts[1]);
- GSRandomRGBDefaultHighlight(&verts[2]);
- GSRandomRGBDefaultHighlight(&verts[3]);
-
- // the wall and floor u and v values go from 0 to maxUV, so uOverW
- // and vOverW == maxUV * invW == 1 / W, and W == z
-
- // left wall
- verts[0].x = 0.0;
- verts[0].y = 0.0;
- verts[0].z = inFrontZ;
- verts[0].invW = kWallsInvW_front;
- verts[0].uOverW = 0.0;
- verts[0].vOverW = kWalls_V * verts[0].invW;
-
- verts[1].x = 0.0;
- verts[1].y = windowHeight;
- verts[1].z = inFrontZ;
- verts[1].invW = kWallsInvW_front;
- verts[1].uOverW = 0.0;
- verts[1].vOverW = 0.0;
-
- verts[2].x = wallWidth;
- verts[2].y = floorDepth + inBackHeight;
- verts[2].z = inBackZ;
- verts[2].invW = kWallsInvW_back;
- verts[2].uOverW = kWalls_U * verts[2].invW;
- verts[2].vOverW = 0.0;
-
- verts[3].x = wallWidth;
- verts[3].y = floorDepth;
- verts[3].z = inBackZ;
- verts[3].invW = kWallsInvW_back;
- verts[3].uOverW = kWalls_U * verts[3].invW;
- verts[3].vOverW = kWalls_V * verts[3].invW;
-
- GSTextureTriList_StoreQuad(
- &gTextureTriList,
- &verts[0],
- &verts[1],
- &verts[2],
- &verts[3],
- gTriFlags,
- kTexture_leftWall);
-
- // back wall
- verts[0].x = wallWidth;
- verts[0].y = floorDepth;
- verts[0].z = inBackZ;
- verts[0].invW = kWallsInvW_back;
- verts[0].uOverW = 0.0;
- verts[0].vOverW = kBackWall_V * verts[0].invW;
-
- verts[1].x = wallWidth;
- verts[1].y = floorDepth + inBackHeight;
- verts[1].z = inBackZ;
- verts[1].invW = kWallsInvW_back;
- verts[1].uOverW = 0.0;
- verts[1].vOverW = 0.0;
-
- verts[2].x = wallWidth + inBackWidth;
- verts[2].y = floorDepth + inBackHeight;
- verts[2].z = inBackZ;
- verts[2].invW = kWallsInvW_back;
- verts[2].uOverW = kBackWall_U * verts[2].invW;
- verts[2].vOverW = 0.0;
-
- verts[3].x = wallWidth + inBackWidth;
- verts[3].y = floorDepth;
- verts[3].z = inBackZ;
- verts[3].invW = kWallsInvW_back;
- verts[3].uOverW = kBackWall_U * verts[3].invW;
- verts[3].vOverW = kBackWall_V * verts[3].invW;
-
- GSTextureTriList_StoreQuad(
- &gTextureTriList,
- &verts[0],
- &verts[1],
- &verts[2],
- &verts[3],
- gTriFlags,
- kTexture_backWall);
-
- // right wall
- verts[0].x = wallWidth + inBackWidth;
- verts[0].y = floorDepth;
- verts[0].z = inBackZ;
- verts[0].invW = kWallsInvW_back;
- verts[0].uOverW = 0.0;
- verts[0].vOverW = kWalls_V * verts[0].invW;
-
- verts[1].x = wallWidth + inBackWidth;
- verts[1].y = floorDepth + inBackHeight;
- verts[1].z = inBackZ;
- verts[1].invW = kWallsInvW_back;
- verts[1].uOverW = 0.0;
- verts[1].vOverW = 0.0;
-
- verts[2].x = windowWidth;
- verts[2].y = windowHeight;
- verts[2].z = inFrontZ;
- verts[2].invW = kWallsInvW_front;
- verts[2].uOverW = kWalls_U * verts[2].invW;
- verts[2].vOverW = 0.0;
-
- verts[3].x = windowWidth;
- verts[3].y = 0.0;
- verts[3].z = inFrontZ;
- verts[3].invW = kWallsInvW_front;
- verts[3].uOverW = kWalls_U * verts[3].invW;
- verts[3].vOverW = kWalls_V * verts[3].invW;
-
- GSTextureTriList_StoreQuad(
- &gTextureTriList,
- &verts[3],
- &verts[2],
- &verts[1],
- &verts[0],
- gTriFlags,
- kTexture_rightWall);
-
- // floor
- verts[0].x = wallWidth;
- verts[0].y = floorDepth + inBackHeight;
- verts[0].z = inBackZ;
- verts[0].invW = kWallsInvW_back;
- verts[0].uOverW = 0.0;
- verts[0].vOverW = kFloor_V * verts[0].invW;
-
- verts[1].x = 0.0;
- verts[1].y = windowHeight;
- verts[1].z = inFrontZ;
- verts[1].invW = kWallsInvW_front;
- verts[1].uOverW = 0.0;
- verts[1].vOverW = 0.0;
-
- verts[2].x = windowWidth;
- verts[2].y = windowHeight;
- verts[2].z = inFrontZ;
- verts[2].invW = kWallsInvW_front;
- verts[2].uOverW = kFloor_U * verts[2].invW;
- verts[2].vOverW = 0.0;
-
- verts[3].x = wallWidth + inBackWidth;
- verts[3].y = floorDepth + inBackHeight;
- verts[3].z = inBackZ;
- verts[3].invW = kWallsInvW_back;
- verts[3].uOverW = kFloor_U * verts[3].invW;
- verts[3].vOverW = kFloor_V * verts[3].invW;
-
- GSTextureTriList_StoreQuad(
- &gTextureTriList,
- &verts[0],
- &verts[1],
- &verts[2],
- &verts[3],
- gTriFlags,
- kTexture_floor);
- }
-
-
- // ===========================================================================
- // GSStoreRandomTris
- // ===========================================================================
- void
- GSStoreRandomTris()
- {
- TQAVTexture verts[3];
- short texture, i;
-
- for (i = 0; i < kBox1_triCount; i++) {
- // get a random vertex which is inside box1
- GSBoundedRandomVTexture(
- &verts[0], kBox1_left, kBox1_right, kBox1_top,
- kBox1_bottom, kBox1_front, kBox1_back);
- GSBoundedRandomVTexture(
- &verts[1], kBox1_left, kBox1_right, kBox1_top,
- kBox1_bottom, kBox1_front, kBox1_back);
- GSBoundedRandomVTexture(
- &verts[2], kBox1_left, kBox1_right, kBox1_top,
- kBox1_bottom, kBox1_front, kBox1_back);
-
- // use either the green or red lava textures. this simply adds
- // 0 or 1 to kTexture_greenLava. we subtract 0.01 just to make
- // sure we never get exactly 2.0.
- texture = kTexture_greenLava + (int) (GSRandomFloat() * 2.0 - 0.01);
-
- GSTextureTriList_StoreTri(
- &gTextureTriList, &verts[0], &verts[1], &verts[2], gTriFlags, texture);
- } // endfor
- }
-
-
- // ===========================================================================
- // GSTextureTriList_New
- // ===========================================================================
- Boolean
- GSTextureTriList_New(
- TGSTextureTriList* inTextureTriList)
- {
- GSAssert_(inTextureTriList);
-
- // we assume inTextureTriList doesn't already point to anything
- inTextureTriList->head = nil;
- inTextureTriList->tail = nil;
- inTextureTriList->triIndex = 0;
-
- // allocate a new TGSTextureTriGroup for the head of the list
- inTextureTriList->head = (TGSTextureTriGroup*) malloc(sizeof(TGSTextureTriGroup));
- inTextureTriList->tail = inTextureTriList->head;
-
- if (inTextureTriList->head == nil) {
- // we don't have enough memory to store a TGSTextureTriGroup,
- // so let the caller know. the fact that we don't have enough
- // memory is indicated by the nil tail pointer.
- return false;
- }
-
- inTextureTriList->head->next = nil;
-
- return true;
- }
-
-
- // ===========================================================================
- // GSTextureTriList_Delete
- // ===========================================================================
- void
- GSTextureTriList_Delete(
- TGSTextureTriList* inTextureTriList)
- {
- TGSTextureTriGroup* currentGroup;
- TGSTextureTriGroup* nextGroup;
-
- GSAssert_(inTextureTriList);
-
- for (currentGroup = inTextureTriList->head, nextGroup = nil;
- currentGroup;
- currentGroup = nextGroup) {
- // save a pointer to the next group, before we free the current one
- nextGroup = currentGroup->next;
-
- free(currentGroup);
- } // endfor
-
- inTextureTriList->head = nil;
- inTextureTriList->tail = nil;
- inTextureTriList->triIndex = 0;
- }
-
-
- // ===========================================================================
- // GSTextureTriList_IsValid
- // ===========================================================================
- Boolean
- GSTextureTriList_IsValid(
- TGSTextureTriList* inTextureTriList)
- {
- GSAssert_(inTextureTriList);
-
- return (inTextureTriList->tail != nil);
- }
-
-
- // ===========================================================================
- // GSTextureTriList_NewTextureTriGroup
- // ===========================================================================
- Boolean
- GSTextureTriList_NewTextureTriGroup(
- TGSTextureTriList* inTextureTriList)
- {
- TGSTextureTriGroup* newGroup = nil;
-
- GSAssert_(inTextureTriList);
-
- if (inTextureTriList->tail == nil) {
- // the tail should never be nil. if it is, it means we were unable
- // to create a new TGSTextureTriGroup at some point. so let the
- // caller know that.
- return false;
- }
-
- if (inTextureTriList->triIndex < kTextureTriGroupCount) {
- // we don't need a new TGSTextureTriGroup because the current
- // one isn't full yet
- return true;
- }
-
- // allocate a new TGSTextureTriGroup at the end of the list
- newGroup = (TGSTextureTriGroup*) malloc(sizeof(TGSTextureTriGroup));
-
- if (newGroup == nil) {
- // there's not enough memory to add a new group, so indicate that
- // in the list and let the caller know
- inTextureTriList->tail = nil;
- return false;
- }
-
- // attach the new group to the end of the list
- newGroup->next = nil;
- inTextureTriList->tail->next = newGroup;
- inTextureTriList->tail = newGroup;
-
- // reset the index
- inTextureTriList->triIndex = 0;
-
- return true;
- }
-
-
- // ===========================================================================
- // GSTextureTriList_StoreTri
- // ===========================================================================
- Boolean
- GSTextureTriList_StoreTri(
- TGSTextureTriList* inTextureTriList,
- TQAVTexture* inVert1,
- TQAVTexture* inVert2,
- TQAVTexture* inVert3,
- unsigned long inFlags,
- short inTexture)
- {
- GSAssert_(inTextureTriList);
- GSAssert_(inVert1);
- GSAssert_(inVert2);
- GSAssert_(inVert3);
-
- // allocate a new TGSTextureTriGroup if necessary
- if (GSTextureTriList_NewTextureTriGroup(inTextureTriList) == false) {
- // there wasn't enough memory
- return false;
- }
-
- // copy the three vertices into the current TGSTextureTri
- inTextureTriList->tail->tris[inTextureTriList->triIndex].v1 = *inVert1;
- inTextureTriList->tail->tris[inTextureTriList->triIndex].v2 = *inVert2;
- inTextureTriList->tail->tris[inTextureTriList->triIndex].v3 = *inVert3;
-
- // copy the flags and texture index into the current TGSTextureTri
- inTextureTriList->tail->tris[inTextureTriList->triIndex].flags = inFlags;
- inTextureTriList->tail->tris[inTextureTriList->triIndex].texture = inTexture;
-
- // we just added a TGSTextureTri, so increment the index
- inTextureTriList->triIndex++;
-
- return true;
- }
-
-
- // ===========================================================================
- // GSTextureTriList_StoreQuad
- // ===========================================================================
- Boolean
- GSTextureTriList_StoreQuad(
- TGSTextureTriList* inTextureTriList,
- TQAVTexture* inVert1,
- TQAVTexture* inVert2,
- TQAVTexture* inVert3,
- TQAVTexture* inVert4,
- unsigned long inFlags,
- short inTexture)
- {
- Boolean result = false;
-
- GSAssert_(inTextureTriList);
- GSAssert_(inVert1);
- GSAssert_(inVert2);
- GSAssert_(inVert3);
- GSAssert_(inVert4);
-
- // first triangle
- result = GSTextureTriList_StoreTri(
- inTextureTriList,
- inVert1,
- inVert2,
- inVert3,
- inFlags,
- inTexture);
-
- if (result == false) {
- return result;
- }
-
- // second triangle
- result = GSTextureTriList_StoreTri(
- inTextureTriList,
- inVert1,
- inVert3,
- inVert4,
- inFlags,
- inTexture);
-
- return result;
- }
-
-
- // ===========================================================================
- // GSTextureTriList_Draw
- // ===========================================================================
- void
- GSTextureTriList_Draw(
- TGSTextureTriList* inTextureTriList,
- TGSDrawInfo* inDrawInfo)
- {
- TGSTextureTriGroup* currentGroup;
- short maxTriIndex, i;
-
- GSAssert_(inTextureTriList);
-
- for (currentGroup = inTextureTriList->head; currentGroup;
- currentGroup = currentGroup->next) {
- if (currentGroup->next == nil) {
- // we're on the last group. the index of the last tri in
- // this group is stored in inTextureTriList->triIndex
- maxTriIndex = inTextureTriList->triIndex;
- } else {
- // the current group is full, so draw the full tri count
- maxTriIndex = kTextureTriGroupCount;
- }
-
- for (i = 0; i < maxTriIndex; i++) {
- GSAssert_(currentGroup->tris[i].texture < kTextureCount);
-
- // set the left draw context's texture
- QASetPtr(inDrawInfo->mContext, kQATag_Texture,
- gTextures[currentGroup->tris[i].texture]);
-
- QADrawTriTexture(inDrawInfo->mContext, ¤tGroup->tris[i].v1,
- ¤tGroup->tris[i].v2, ¤tGroup->tris[i].v3,
- currentGroup->tris[i].flags);
- } // endfor
- } // endfor
- }